package q1.project.modules.system.role.service;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import java.util.List;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import q1.project.common.context.TenantContext;
import q1.project.common.enums.EnableStatusEnum;
import q1.project.modules.system.role.entity.*;
import q1.project.modules.system.role.entity.MenuEntity;
import q1.project.modules.system.role.entity.QMenuEntity;

/**
 * 用户角色权限服务
 *
 * @author Q1 Team
 * @version 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserRoleService {

  private final JPAQueryFactory queryFactory;
  private final EntityManager entityManager;

  public List<RoleEntity> findRolesByUserId(String userId) {
    QUserRoleEntity qUserRole = QUserRoleEntity.userRoleEntity;
    QRoleEntity qRole = QRoleEntity.roleEntity;

    return queryFactory
        .select(qRole)
        .from(qUserRole)
        .join(qRole)
        .on(qUserRole.roleId.eq(qRole.id))
        .where(qUserRole.userId.eq(userId), qRole.status.eq(EnableStatusEnum.ACTIVE))
        .fetch();
  }

  public List<PermissionEntity> findPermissionsByRoleId(String roleId) {
    QRolePermissionEntity qRolePermission = QRolePermissionEntity.rolePermissionEntity;
    QPermissionEntity qPermission = QPermissionEntity.permissionEntity;

    return queryFactory
        .select(qPermission)
        .from(qRolePermission)
        .join(qPermission)
        .on(qRolePermission.permissionId.eq(qPermission.id))
        .where(qRolePermission.roleId.eq(roleId), qPermission.status.eq(EnableStatusEnum.ACTIVE))
        .fetch();
  }

  public List<PermissionEntity> findPermissionsByUserId(String userId) {
    QUserRoleEntity qUserRole = QUserRoleEntity.userRoleEntity;
    QRolePermissionEntity qRolePermission = QRolePermissionEntity.rolePermissionEntity;
    QPermissionEntity qPermission = QPermissionEntity.permissionEntity;

    return queryFactory
        .selectDistinct(qPermission)
        .from(qUserRole)
        .join(qRolePermission)
        .on(qUserRole.roleId.eq(qRolePermission.roleId))
        .join(qPermission)
        .on(qRolePermission.permissionId.eq(qPermission.id))
        .where(qUserRole.userId.eq(userId), qPermission.status.eq(EnableStatusEnum.ACTIVE))
        .fetch();
  }

  @Transactional(rollbackFor = Exception.class)
  public void assignRolesToUser(String userId, Set<String> roleIds) {
    // 先删除现有关联
    removeUserRoles(userId);

    // 创建新关联
    for (String roleId : roleIds) {
      UserRoleEntity userRole = new UserRoleEntity();
      entityManager.persist(userRole);
    }

    log.info("为用户 {} 分配角色: {}", userId, roleIds);
  }

  @Transactional(rollbackFor = Exception.class)
  public void assignPermissionsToRole(String roleId, Set<String> permissionIds) {
    // 先删除现有关联
    removeRolePermissions(roleId);

    // 创建新关联
    for (String permissionId : permissionIds) {
      RolePermissionEntity rolePermission = new RolePermissionEntity();
      entityManager.persist(rolePermission);
    }

    log.info("为角色 {} 分配权限: {}", roleId, permissionIds);
  }

  @Transactional(rollbackFor = Exception.class)
  public void removeUserRoles(String userId) {
    QUserRoleEntity qUserRole = QUserRoleEntity.userRoleEntity;

    long deleted = queryFactory.delete(qUserRole).where(qUserRole.userId.eq(userId)).execute();

    log.info("删除用户 {} 的所有角色关联，共 {} 条", userId, deleted);
  }

  public List<MenuEntity> findMenusByRoleId(String roleId) {
    QRoleMenuEntity qRoleMenu = QRoleMenuEntity.roleMenuEntity;
    QMenuEntity qMenu = QMenuEntity.menuEntity;

    return queryFactory
        .select(qMenu)
        .from(qRoleMenu)
        .join(qMenu)
        .on(qRoleMenu.menuId.eq(qMenu.id))
        .where(qRoleMenu.roleId.eq(roleId), qMenu.status.eq(EnableStatusEnum.ACTIVE))
        .fetch();
  }

  public List<MenuEntity> findMenusByUserId(String userId) {
    String tenantId = TenantContext.getTenantId();
    QUserRoleEntity qUserRole = QUserRoleEntity.userRoleEntity;
    QRoleMenuEntity qRoleMenu = QRoleMenuEntity.roleMenuEntity;
    QMenuEntity qMenu = QMenuEntity.menuEntity;

    return queryFactory
        .selectDistinct(qMenu)
        .from(qUserRole)
        .join(qRoleMenu)
        .on(qUserRole.roleId.eq(qRoleMenu.roleId))
        .join(qMenu)
        .on(qRoleMenu.menuId.eq(qMenu.id))
        .where(
            qUserRole.userId.eq(userId),
            qUserRole.tenantId.eq(tenantId),
            qRoleMenu.tenantId.eq(tenantId),
            qMenu.status.eq(EnableStatusEnum.ACTIVE))
        .orderBy(qMenu.sortOrder.asc())
        .fetch();
  }

  @Transactional(rollbackFor = Exception.class)
  public void assignMenusToRole(String roleId, Set<String> menuIds) {
    // 先删除现有关联
    removeRoleMenus(roleId);

    // 创建新关联
    for (String menuId : menuIds) {
      RoleMenuEntity roleMenu = new RoleMenuEntity();
      entityManager.persist(roleMenu);
    }

    log.info("为角色 {} 分配菜单: {}", roleId, menuIds);
  }

  @Transactional(rollbackFor = Exception.class)
  public void removeRolePermissions(String roleId) {
    QRolePermissionEntity qRolePermission = QRolePermissionEntity.rolePermissionEntity;

    long deleted =
        queryFactory.delete(qRolePermission).where(qRolePermission.roleId.eq(roleId)).execute();

    log.info("删除角色 {} 的所有权限关联，共 {} 条", roleId, deleted);
  }

  @Transactional(rollbackFor = Exception.class)
  public void removeRoleMenus(String roleId) {
    QRoleMenuEntity qRoleMenu = QRoleMenuEntity.roleMenuEntity;

    long deleted = queryFactory.delete(qRoleMenu).where(qRoleMenu.roleId.eq(roleId)).execute();

    log.info("删除角色 {} 的所有菜单关联，共 {} 条", roleId, deleted);
  }

  @Transactional(rollbackFor = Exception.class)
  public void deleteByUserId(String userId) {
    QUserRoleEntity qUserRole = QUserRoleEntity.userRoleEntity;

    long deleted = queryFactory.delete(qUserRole).where(qUserRole.userId.eq(userId)).execute();

    log.info("物理删除用户 {} 的所有角色关联，共 {} 条", userId, deleted);
  }
}
